from fastapi import APIRouter, Depends, HTTPException, Request, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm, HTTPBearer, HTTPAuthorizationCredentials
from pydantic import BaseModel
from typing import Optional, Dict
import os
import logging
from datetime import datetime, timedelta
import jwt
from ..services.jwt_service import JWTService, jwt_required

# 配置日志
logger = logging.getLogger(__name__)

router = APIRouter(prefix="/auth", tags=["auth"])

# 模拟用户数据库
DEMO_USERS = {
    "demo": {
        "username": "demo",
        "full_name": "Demo User",
        "email": "demo@example.com",
        "hashed_password": "demo123",  # 在真实系统中应该使用哈希密码
        "disabled": False
    },
    "visitor": {
        "username": "visitor",
        "full_name": "Visitor",
        "email": "visitor@example.com",
        "hashed_password": "visitor",  # 在真实系统中应该使用哈希密码
        "disabled": False
    }
}

# 认证相关的数据模型
class Token(BaseModel):
    access_token: str
    token_type: str
    expires_at: int

class TokenData(BaseModel):
    username: Optional[str] = None

class User(BaseModel):
    username: str
    email: Optional[str] = None
    full_name: Optional[str] = None
    disabled: Optional[bool] = None

class UserInDB(User):
    hashed_password: str

class TokenValidationResponse(BaseModel):
    valid: bool
    user_id: Optional[str] = None
    username: Optional[str] = None
    message: str

# JWT服务
jwt_service = JWTService()

# 获取环境变量
JWT_SECRET = os.getenv("JWT_SECRET", "visitor_auth_secret_key_very_secure")
JWT_EXPIRES_IN = os.getenv("JWT_EXPIRES_IN", "20d")

# 创建OAuth2密码承载模式
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/token")

def verify_password(plain_password, hashed_password):
    """验证密码（简化版示例，实际应使用哈希）"""
    return plain_password == hashed_password

def get_user(db, username: str):
    """从模拟数据库获取用户"""
    if username in db:
        user_dict = db[username]
        return UserInDB(**user_dict)
    return None

def authenticate_user(fake_db, username: str, password: str):
    """认证用户"""
    user = get_user(fake_db, username)
    if not user:
        return False
    if not verify_password(password, user.hashed_password):
        return False
    return user

def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
    """创建访问令牌"""
    to_encode = data.copy()
    now = datetime.utcnow()
    if expires_delta:
        expire = now + expires_delta
    else:
        expire = now + timedelta(days=20)  # 默认20天
    to_encode.update({"exp": expire, "iat": now})
    encoded_jwt = jwt.encode(to_encode, JWT_SECRET, algorithm="HS256")
    return encoded_jwt, int(expire.timestamp())

@router.post("/token", response_model=Token)
async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
    """获取访问令牌"""
    logger.info(f"Login attempt for user: {form_data.username}")
    
    # 认证用户
    user = authenticate_user(DEMO_USERS, form_data.username, form_data.password)
    if not user:
        logger.warning(f"Invalid username or password for: {form_data.username}")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid username or password",
            headers={"WWW-Authenticate": "Bearer"},
        )
    
    # 解析过期时间
    try:
        expires_in = jwt_service.parse_expiration_time(JWT_EXPIRES_IN)
    except ValueError as e:
        logger.error(f"Invalid JWT_EXPIRES_IN value: {JWT_EXPIRES_IN}")
        expires_in = timedelta(days=20)  # 默认20天
    
    # 创建JWT令牌
    token_data = {
        "sub": user.username,
        "name": user.full_name,
        "email": user.email
    }
    access_token, expires_at = create_access_token(token_data, expires_in)
    
    logger.info(f"Login successful for user: {user.username}")
    return {
        "access_token": access_token,
        "token_type": "bearer",
        "expires_at": expires_at
    }

@router.get("/me", response_model=User)
async def read_users_me(current_user: dict = Depends(jwt_required)):
    """获取当前用户信息"""
    username = current_user.get("sub", "")
    
    if not username:
        logger.warning("Invalid token: missing 'sub' claim")
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid token"
        )
    
    user = get_user(DEMO_USERS, username)
    if user is None:
        logger.warning(f"User not found: {username}")
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found"
        )
    
    logger.info(f"User details requested for: {username}")
    return user

@router.get("/verify", response_model=TokenValidationResponse)
async def verify_token(credentials: HTTPAuthorizationCredentials = Depends(HTTPBearer())):
    """
    验证JWT令牌是否有效
    """
    try:
        token = credentials.credentials
        # 解码并验证令牌
        payload = jwt_service.verify_jwt(token)
        
        # 构建成功响应
        return TokenValidationResponse(
            valid=True,
            user_id=payload.get("sub"),
            username=payload.get("username"),
            message="Token is valid"
        )
    except HTTPException as e:
        # 令牌验证失败
        return TokenValidationResponse(
            valid=False,
            message=str(e.detail)
        )
    except Exception as e:
        logger.error(f"Unexpected error during token verification: {str(e)}")
        return TokenValidationResponse(
            valid=False,
            message="Invalid token"
        )

@router.get("/protected")
async def protected_route(current_user: dict = Depends(jwt_required)):
    """
    受保护的路由示例，需要有效的JWT令牌才能访问
    """
    return {
        "message": "You have access to protected route",
        "user_id": current_user.get("sub"),
        "username": current_user.get("username")
    }

@router.get("/visitor-token")
async def get_visitor_token():
    """获取游客访问令牌（简化访问）"""
    token_data = {
        "sub": "visitor",
        "name": "Visitor",
        "email": "visitor@example.com"
    }
    
    try:
        expires_in = jwt_service.parse_expiration_time(JWT_EXPIRES_IN)
    except ValueError:
        expires_in = timedelta(days=20)  # 默认20天
    
    access_token, expires_at = create_access_token(token_data, expires_in)
    
    logger.info("Generated visitor token")
    return {
        "access_token": access_token,
        "token_type": "bearer",
        "expires_at": expires_at
    } 